/*
 * @Descripttion : 分页
 * @Author       : QianFox Team
 * @Date         : 2022-04-15 17:06:12
 * @LastEditors  : Please set LastEditors
 * @LastEditTime : 2023-02-28 16:45:07
 */

import {
    _verificationEl,
    _verificationItem,
    _verificationIsBool,
    _verificationIsArray,
    _verificationIntOdd,
    _verificationInt,
    _verificationPageSize,
    _verificationCallback,
} from './common/verification';
import { _isIntNum, _typeOf } from './common/utils';
import { message } from './message';

const typeList = ['text', 'solid', 'plain']; // 类型：分页样式
const sizeList = ['small', 'mini']; // 尺寸: 分页尺寸

function Pagination({ el, total, currentPage, callback }, { type, size, pageSize, pageNum, pageSizeList, isShowTotal, isShowJump, isShowSize }) {
    // 配置
    this.type = type || 'text';
    this.size = size || 'small';
    this.pageSize = pageSize || 10;
    this.pageNum = pageNum || 9;
    this.pageSizeList = pageSizeList || [10, 20, 50, 100];
    this.isShowTotal = isShowTotal || false;
    this.isShowJump = isShowJump || false;
    this.isShowSize = isShowSize || false;
    // 数据
    this.el = el || null;
    this.total = total || 0;
    this.currentPage = currentPage > Math.ceil(total / pageSize) ? Math.ceil(total / pageSize) : currentPage;
    this.callback = callback || null;

    this.pages = Math.ceil(total / this.pageSize) || 0;
}

Pagination.prototype._appendPagination = function () {
    $(this.el).empty().append(this._paginationHtml());
    this._bindChangePage();
};

Pagination.prototype._paginationHtml = function () {
    return [
        `<div class="foxui-pagination foxui-type-${this.type} foxui-size-${this.size}" ${this.total < 1 ? 'style="display:none"' : ''}>`,
        `${this.isShowTotal ? this._totalHtml(this.total) : ''}`,
        `<button class="foxui-size-${this.size} foxui-text foxui-pagination-prev ${this.currentPage == 1 ? 'is-disabled' : ''}" ${this.currentPage == 1 ? 'disabled' : ''}>`,
        '<i class="foxui-icon-xiangzuo-o"></i>',
        '</button>',
        '<ul class="foxui-pagination-list">',
        `${this._pagesHtml()}`,
        '</ul>',
        `<button class="foxui-size-${this.size} foxui-text foxui-pagination-next ${this.currentPage == this.pages ? 'is-disabled' : ''}" ${this.currentPage == this.pages ? 'disabled' : ''}>`,
        '<i class="foxui-icon-xiangyou-o"></i>',
        '</button>',
        `${this.isShowSize ? this._pageSizeHtml() : ''}`,
        `${this.isShowJump ? this._jumpHtml() : ''}`,
        '</div>',
    ].join('');
};

Pagination.prototype._totalHtml = function () {
    return `<div class="foxui-pagination__total">共 ${this.total} 条</div>`;
};

Pagination.prototype._pagesHtml = function () {
    let pageHtmlArr = [];
    if (this.total / this.pageSize > this.pageNum) {
        for (let i = 1; i <= this.pageNum; i++) {
            if (i == 1) {
                // 第一个按钮
                pageHtmlArr.push(`<li class="page${1 === this.currentPage ? ' active' : ''}">${1}</li>`);
            } else if (i == 2) {
                // 第二个按钮
                if (this.currentPage > Math.ceil(this.pageNum / 2)) {
                    pageHtmlArr.push(`<li class="page more prev"></li>`);
                } else {
                    pageHtmlArr.push(`<li class="page${2 === this.currentPage ? ' active' : ''}">${2}</li>`);
                }
            } else if (i == this.pageNum - 1) {
                // 倒数第二个按钮
                if (this.currentPage > this.pages - Math.ceil(this.pageNum / 2)) {
                    pageHtmlArr.push(`<li class="page${this.pages - 1 === this.currentPage ? ' active' : ''}">${this.pages - 1}</li>`);
                } else {
                    pageHtmlArr.push(`<li class="page more next"></li>`);
                }
            } else if (i == this.pageNum) {
                // 倒数第一个按钮
                pageHtmlArr.push(`<li class="page${this.pages === this.currentPage ? ' active' : ''}">${this.pages}</li>`);
            } else {
                // 中间按钮
                const minMiddlePage = Math.ceil(this.pageNum / 2);
                const maxMiddlePage = this.pages - Math.ceil(this.pageNum / 2);
                if (this.currentPage < minMiddlePage) {
                    // 当前页码开始位置
                    pageHtmlArr.push(`<li class="page${i === this.currentPage ? ' active' : ''}">${i}</li>`);
                } else if (this.currentPage > maxMiddlePage) {
                    // 当前页码未尾位置
                    const cPage = this.pages - this.pageNum + i;
                    pageHtmlArr.push(`<li class="page${cPage === this.currentPage ? ' active' : ''}">${cPage}</li>`);
                } else {
                    // 当前页码中间位置
                    const startPage = this.currentPage - Math.ceil((this.pageNum - 4) / 2);
                    pageHtmlArr.push(`<li class="page${startPage + i - 2 === this.currentPage ? ' active' : ''}">${startPage + i - 2}</li>`);
                }
            }
        }
    } else {
        for (let i = 1; i <= this.pages; i++) {
            pageHtmlArr.push(`<li class="page${i === this.currentPage ? ' active' : ''}">${i}</li>`);
        }
    }
    return pageHtmlArr.join('');
};

Pagination.prototype._pageSizeHtml = function () {
    let htmlArr = [];
    this.pageSizeList.forEach(item => {
        htmlArr.push(`<li class="foxui-select-item" data-size="${item}">${item} 条/页</li>`);
    });
    return [
        '<div class="foxui-pagination__sizes">',
        '<div class="foxui-select">',
        '<div class="foxui-select-handle foxui-select-icon">',
        `<input class="foxui-select-input foxui-size-${this.size}" readonly="readonly" placeholder="条/页" value="${this.pageSize} 条/页" />`,
        '</div>',
        '<div class="foxui-select-menu">',
        '<ul class="foxui-select-slide">',
        `${htmlArr.join('')}`,
        '</ul>',
        '</div>',
        '</div>',
        '</div>',
    ].join('');
};

Pagination.prototype._jumpHtml = function () {
    return [
        '<div class="foxui-pagination__jump">',
        '<div class="foxui-input-group">',
        '<label>前往</label>',
        `<input class="foxui-size-${this.size}" placeholder="页码" required value="1" />`,
        '<label>页</label>',
        '</div>',
        '</div>',
    ].join('');
};

/**
 * @description: 页码改变时，绑定相关的函数
 * @param {*}
 * @return {*}
 * @Date: 2022-04-17 00:13:25
 */
Pagination.prototype._bindChangePage = function () {
    this._bindClickPage();
    this._bindClickPrev();
    this._bindClickNext();
    this._bindClickPrevBySize();
    this._bindClickNextBySize();
    this._bindPressEnterForInput();
    this._bindBlueForInput();
    this._bindChangePageSize();
};

/**
 * @description: 点击 page 时，改变页码及执行相关回调函数
 * @param {*}
 * @return {*}
 * @Date: 2022-04-17 00:08:17
 */
Pagination.prototype._bindClickPage = function () {
    let that = this;
    $(this.el)
        .find('.page')
        .not('.active')
        .not('.more')
        .off('click')
        .on('click', function () {
            that.currentPage = parseInt($(this).text());
            that._runCallback();
        });
};

/**
 * @description: 点击上一页时，改变页码及执行相关回调函数
 * @param {*}
 * @return {*}
 * @Date: 2022-04-17 00:24:21
 */
Pagination.prototype._bindClickPrev = function () {
    let that = this;
    $(this.el)
        .find('.foxui-pagination-prev')
        .off('click')
        .on('click', function () {
            that.currentPage -= 1;
            that._runCallback();
        });
};

/**
 * @description: 点击下一页时，改变页码及执行相关回调函数
 * @param {*}
 * @return {*}
 * @Date: 2022-04-17 00:25:45
 */
Pagination.prototype._bindClickNext = function () {
    let that = this;
    $(this.el)
        .find('.foxui-pagination-next')
        .off('click')
        .on('click', function () {
            that.currentPage += 1;
            that._runCallback();
        });
};

/**
 * @description: 点击上一列表页，执行相关回调函数
 * @param {*}
 * @return {*}
 * @Date: 2022-04-17 00:29:25
 */
Pagination.prototype._bindClickPrevBySize = function () {
    let that = this;
    $(this.el)
        .find('.foxui-pagination-list .page.prev')
        .off('click')
        .on('click', function () {
            const resPage = that.currentPage - Math.ceil(that.pageNum / 2);
            if (resPage > 0) {
                that.currentPage = that.currentPage - Math.ceil(that.pageNum / 2);
            } else {
                that.currentPage = 1;
            }
            that._runCallback();
        });
};

/**
 * @description: 点击下一列表页，执行相关回调函数
 * @param {*}
 * @return {*}
 * @Date: 2022-04-17 00:30:14
 */
Pagination.prototype._bindClickNextBySize = function () {
    let that = this;
    $(this.el)
        .find('.foxui-pagination-list .page.next')
        .off('click')
        .on('click', function () {
            const resPage = that.currentPage + Math.ceil(that.pageNum / 2);
            if (resPage < that.pages) {
                that.currentPage = that.currentPage + Math.ceil(that.pageNum / 2);
            } else {
                that.currentPage = that.pages;
            }
            that._runCallback();
        });
};

/**
 * @description: 改变 pageSize 时，执行相关回调函数
 * @param {*}
 * @return {*}
 * @Date: 2022-04-17 00:43:39
 */
Pagination.prototype._bindChangePageSize = function () {
    let that = this;
    $(this.el)
        .find('.foxui-pagination__sizes .foxui-select-item')
        .off('click')
        .on('click', function () {
            const pageSize = $(this).attr('data-size');
            that.pageSize = parseInt(pageSize);
            that.currentPage = 1;
            that._runCallback();
        });
};

/**
 * @description: 按下回车时，执行相关回调函数
 * @param {*}
 * @return {*}
 * @Date: 2022-04-17 00:34:30
 */
Pagination.prototype._bindPressEnterForInput = function () {
    let that = this;
    $(this.el)
        .find('.foxui-pagination__jump input')
        .off('keypress')
        .on('keypress', function (event) {
            if (event.which == 13) {
                if (_isIntNum(event.target.value)) {
                    const cPage = event.target.value <= that.pages ? parseInt(event.target.value) : that.pages;
                    that.currentPage = cPage;
                    that._runCallback();
                } else {
                    message({
                        text: '请输入正整数！',
                        type: 'danger',
                    });
                    event.target.value = that.currentPage;
                }
            }
        });
};

/**
 * @description: 失去焦点时，设置输入框的值为 1；
 * @param {*}
 * @return {*}
 * @Date: 2022-04-17 00:36:57
 */
Pagination.prototype._bindBlueForInput = function () {
    $(this.el)
        .find('.foxui-pagination__jump input')
        .off('blur')
        .on('blur', function (event) {
            event.target.value = 1;
        });
};

/**
 * @description: 执行回调数据
 * @param {*}
 * @return {*}
 * @Date: 2022-04-16 23:54:20
 */
Pagination.prototype._runCallback = function () {
    if (_typeOf(this.callback) === 'function') {
        this.callback({ currentPage: this.currentPage, pageSize: this.pageSize, total: this.total }, this._updatePagination.bind(this));
    }
};

/**
 * @description: 更新页码
 * @param {*} total
 * @param {*} pageSize
 * @param {*} currentPage
 * @return {*}
 * @Date: 2022-04-17 00:02:48
 */
Pagination.prototype._updatePagination = function ({ total, pageSize, currentPage }) {
    // 校验 total
    total != 0 && _verificationInt(total, true, 'total');
    // 校验 pageSize
    _verificationPageSize(pageSize, this.pageSizeList, true, 'pageSize');
    // 校验 currentPage
    _verificationInt(currentPage, true, 'currentPage');
    // 更新数据
    this.total = total;
    pageSize ? (this.pageSize = pageSize) : (pageSize = this.pageSize);
    if (currentPage > Math.ceil(total / pageSize)) {
        this.currentPage = Math.ceil(total / pageSize);
    } else {
        this.currentPage = currentPage;
    }
    this.pages = Math.ceil(total / pageSize);
    // 更新页码
    this._appendPagination();
};

/**
 * @description: 创建分页
 * @param {*} el            页码容器节点
 * @param {*} type          页码类型样式 (text、solid、plain)
 * @param {*} size          页码尺寸(small(默认), mini)
 * @param {*} isShowJump    是否显示前往第几页
 * @param {*} isShowTotal   是否显示共有多少条
 * @param {*} isShowSize    是否显示选择每页显示多少条
 * @param {*} pageSize      每页显示多少条 (10，20，50，100)
 * @param {*} pageSizeList  每页显示条数列表 [10，20，50，100]
 * @param {*} total         共有多少条 (total > 0的正整数)
 * @param {*} currentPage   当前是第几页 (currentPage > 0的正整数)
 * @param {*} pageNum       显示几个页码 (pageNum >0 的正整数的奇数)
 * @param {*} callback      页码改变时的回调函数（传入异步请求获取的数据）
 * @return {*}
 * @Date: 2022-04-16 21:18:14
 */
function pagination(data, option) {
    data = data || {};
    option = option || {};
    const { el, total, currentPage, onchange } = data;
    const { type, size, pageSize, pageNum, pageSizeList = [10, 20, 50, 100], isShowTotal, isShowJump, isShowSize } = option;

    // 校验 el
    _verificationEl(el, true, 'el');
    // 校验 total
    total != 0 && _verificationInt(total, true, 'total');
    // 校验 currentPage
    _verificationInt(currentPage, true, 'currentPage');
    // 校验 callback
    _verificationCallback(onchange, true, 'onchange');
    // 校验 type
    _verificationItem(type, typeList, true, 'type');
    // 校验 size
    _verificationItem(size, sizeList, true, 'size');
    // 校验 pageSizeList
    if (_verificationIsArray(pageSizeList, true, 'pageSizeList')) {
        pageSizeList.forEach(item => {
            _verificationInt(item, true, item);
        });
    }
    // 校验 pageSize
    _verificationPageSize(pageSize, pageSizeList, true, 'pageSize');
    // 校验 pageNum
    _verificationIntOdd(pageNum, true, 'pageNum');
    // 校验 isShowJump
    _verificationIsBool(isShowJump, true, 'isShowJump');
    // 校验 isShowTotal
    _verificationIsBool(isShowTotal, true, 'isShowTotal');
    // 校验 isShowSize
    _verificationIsBool(isShowSize, true, 'isShowSize');

    // 分页实例化
    const newPagination = new Pagination({ el, total, currentPage, callback: onchange }, { type, size, pageSize, pageNum, pageSizeList, isShowTotal, isShowJump, isShowSize });
    // 分页初始化
    newPagination._appendPagination();
    // 返回对象, 供调用内部方法
    return newPagination;
}

export { pagination };
